//////////////////////////////////////////////
// JpgBitStream.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Class ------------------------------------

namespace nkImages::jpg
{
	// Aimed at scan data, with all the specs of it implemented
	// For instance, avoiding FF[00] bytes
	class JpgBitStream final
	{
		public :

			// Functions
			// Constructor
			JpgBitStream (const unsigned char* data) noexcept
			:	_data (data)
			{
				// Nothing todo
			}

			// Bit getting
			unsigned int getNextBits (unsigned int count)
			{
				// Check feedback value and pre feed from it
				unsigned int feedbackCount = count < _feedbackDataSize ? count : _feedbackDataSize ; //std::min(count, _feedbackDataSize) ;
				unsigned int result = _feedbackData >> (_feedbackDataSize - feedbackCount) ;
				_feedbackData &= ~(0xffffffff << (_feedbackDataSize - feedbackCount)) ;
				_feedbackDataSize -= feedbackCount ;
				count -= feedbackCount ;

				while (count > 0)
				{
					// Get next number of bits and add them
					unsigned int invBitCounter = 8u - _bitCounter ;
					unsigned int nextCount = (count < invBitCounter) ? count : invBitCounter ; //std::min(count, 8u - _bitCounter) ;
					result = (result << nextCount) + ((*_data & (0b11111111 >> _bitCounter)) >> (invBitCounter - nextCount)) ;

					// Forward
					_bitCounter += nextCount ;
					_data += (_bitCounter >> 3) * (1 + (*_data == 255 ? 1 : 0)) ;
					_bitCounter %= 8u ;
					count -= nextCount ;
				}

				return result ;
			}

			// Feedback
			void feedback (unsigned int value, unsigned int count)
			{
				_feedbackData += value << _feedbackDataSize ;
				_feedbackDataSize += count ;
			}

		public :

			// Attributes
			// Stream & state holding
			const unsigned char* _data ;
			unsigned int _bitCounter = 0u ;

			unsigned int _feedbackData = 0u ;
			unsigned int _feedbackDataSize = 0u ;
	} ;
}